package handler

import (
	"archive/tar"
	"bytes"
	"compress/gzip"
	"fmt"
	"gofile/src/config"
	"gofile/src/util"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"
)

// CompressDirToTarGz 定义一个方法可以，参数是个字符串，代表目录名，方法实现目录压缩成一个tar.gz格式的文件作为返回值
func CompressDirToTarGz(dirPath string) ([]byte, error) {
	// create a buffer to write our archive to.
	buf := new(bytes.Buffer)

	// create a new tar archive.
	tw := tar.NewWriter(buf)

	// walk through every file in the folder.
	filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// get the header for the file.
		header, err := tar.FileInfoHeader(info, info.Name())
		if err != nil {
			return err
		}

		// update the name to correctly reflect the desired destination when untaring.
		header.Name = strings.TrimPrefix(path, filepath.Dir(dirPath)+"/")

		// write the header.
		if err := tw.WriteHeader(header); err != nil {
			return err
		}

		// if the file is not a regular file (in our case, it's a directory), skip it.
		if !info.Mode().IsRegular() {
			return nil
		}

		// open files for taring.
		file, err := os.Open(path)
		if err != nil {
			return err
		}
		defer file.Close()

		// copy file data into tar writer
		if _, err := io.Copy(tw, file); err != nil {
			return err
		}

		return nil
	})

	// close the tar writer
	if err := tw.Close(); err != nil {
		return nil, err
	}

	// compress the buffer using gzip.
	var compressed bytes.Buffer
	gw := gzip.NewWriter(&compressed)
	if _, err := gw.Write(buf.Bytes()); err != nil {
		return nil, err
	}
	if err := gw.Close(); err != nil {
		return nil, err
	}

	return compressed.Bytes(), nil
}
func DownloadFileHandler(w http.ResponseWriter, r *http.Request) {
	params := r.URL.Query()
	file := params.Get("file")
	myCfg := config.GetConfig()
	path := myCfg.File.Dir + file

	// check if the file exists
	if _, err := os.Stat(path); os.IsNotExist(err) {
		// handle file not found error
		util.ProcessResult("文件不存在", err, w)
	} else {
		// file exists, continue with download logic

		// check if the path is a directory
		if fileInfo, err := os.Stat(path); err == nil && fileInfo.IsDir() {
			// path is a directory

			// path is a directory
			// compress the directory to a tar.gz file
			compressed, err := CompressDirToTarGz(path)
			if err != nil {
				// handle error
				util.ProcessResult("目录"+path+"压缩错误", err, w)
				return
			}

			// set the headers
			w.Header().Set("Content-Disposition", "attachment; filename="+filepath.Base(path)+".tar.gz")
			w.Header().Set("Content-Type", "application/octet-stream")
			w.Header().Set("Content-Length", fmt.Sprintf("%d", len(compressed)))

			// send the file
			http.ServeContent(w, r, filepath.Base(path)+".tar.gz", time.Now(), bytes.NewReader(compressed))
		} else if err == nil {
			// path is a file

			// open the file
			file, err := os.Open(path)
			if err != nil {
				// handle error
				util.ProcessResult("文件"+path+"打开错误", err, w)
				return
			}

			defer file.Close()

			// get the file size
			fileInfo, err := file.Stat()
			if err != nil {
				// handle error
			}
			fileSize := fileInfo.Size()

			// set the headers
			w.Header().Set("Content-Disposition", "attachment; filename="+fileInfo.Name())
			w.Header().Set("Content-Type", "application/octet-stream")
			w.Header().Set("Content-Length", fmt.Sprintf("%d", fileSize))

			// send the file
			http.ServeContent(w, r, fileInfo.Name(), fileInfo.ModTime(), file)
		} else {
			// handle error
			util.ProcessResult("文件"+path+"状态错误", err, w)
			return
		}
	}
}
